#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>


struct boot_head {
    unsigned char vector[0x20];
    unsigned int  width; // 0x20
    unsigned char head[4];  // 0x24
    unsigned char key[4];   // 0x28
    unsigned char version[4]; // 0x2c
    unsigned int source;  // 0x30
    unsigned int fsbl_lenth; // 0x34
    unsigned int fsbl_load;  // 0x38
    unsigned int fsbl_exec;             // 0x3c
    unsigned int fsbl_total_length;    // 0x40
    unsigned char qspi [4];                 // 0x44
    unsigned char boot_head_sum[4];    // 0x48
    unsigned char user_define[0x4c];     // 0x4c~0x97
    unsigned int image_head_table;    // 0x98
    unsigned int partition_head_table;  // 0x9c
};

union BOOT_HEAD_U{
    unsigned char buff[0xa0];
    struct boot_head data;
};

void print_head(struct boot_head * head)
{
    printf("\n-------------------boot_head-----------------\n");
    printf("width:%x \n", head->width);
    printf("source:%x \n", head->source);
    printf("fsbl_lenth: %x \n", head->fsbl_lenth);
    printf("fsbl_load: %x \n", head->fsbl_load);
    printf("fsbl_exec: %x \n", head->fsbl_exec);
    printf("image_head_table: %x \n", head->image_head_table);
    printf("partition_head_table: %x \n", head->partition_head_table);
}

typedef struct {
    unsigned int version ;
    unsigned int count ;
    unsigned int fist_partition_header_offset;
    unsigned int fist_image_header_offset;
    unsigned int header_Auth;
    unsigned char resvered[4];
} image_header_table_t;

typedef union {
    unsigned char buff[0x40];
    image_header_table_t header_table;
}image_header_table;

void print_image_header_tabel(image_header_table_t * head)
{
    printf("\n-----------------------image_header_tabel----------------------\n");
    printf("version : 0x%x\n", head-> version);
    printf("count : 0x%x\n", head-> count);
    printf("fist_partition : 0x%x\n", head-> fist_partition_header_offset);
    printf("fist_image : 0x%x\n", head-> fist_image_header_offset);
    printf("header_Auth : 0x%x\n", head-> header_Auth);
    printf("resverved : %x %x %x %x\n", head-> resvered[0], \
            head->resvered[1],
            head->resvered[2],
            head->resvered[3]);
}

typedef struct {
    unsigned int next_image_header ;
    unsigned int partition_header;
    unsigned int reserved;
    unsigned int parttition_count ;
    unsigned char image_name[0x30];
} image_header_t;

typedef union {
    unsigned char buff[0x40];
    image_header_t header;
}image_header;

void print_image_header(image_header_t * head)
{
    printf("\n-----------------------image_header--------------------------\n");
    printf("next_image_header : 0x%x\n", head-> next_image_header);
    printf("partition_header : 0x%x\n", head-> partition_header);
    printf("parttition_count: 0x%x\n", head-> parttition_count);
    printf("imag_name: ");
    unsigned char*buff;
    unsigned int  data;
    for(int j = 0 ; j < 12; j++) {
        data = htonl(*(int*)&head->image_name[j*4]);
        buff = (unsigned char * )& data;
        for(int i= 0 ; i< 4 ; i++)
        {
            if(buff[i] == 0){ printf("\n"); return;}
            printf("%c", buff[i]);
        }
    }
    printf("\n");
}

typedef struct {
    unsigned int encry ;
    unsigned int unencry;
    unsigned int auth;
    unsigned int load_addr;
    unsigned int exec_add;
    unsigned int data_word_offset_img;
    unsigned int attribute;
    unsigned int section_count;
    unsigned int sum;
    unsigned int image_word_offset;
    unsigned int auth_c_off;
    unsigned int buff[4];
    unsigned int head_sum;
} part_header_t;

typedef union {
    unsigned char buff[0x40];
    part_header_t part_header;
}part_header;
void print_part_header(part_header_t *head, int count)
{
    printf("\n---------------------part_header %d-----------------\n", count);
    printf("encry 0x%x: 0x%x \n", head-> encry, head-> encry *4);
    printf("unencry: 0x%x: 0x%x\n", head->unencry, head->unencry*4);
    printf("auth: 0x%x: 0x%x\n", head->auth, head->auth*4);
    printf("load_addr: 0x%x\n", head-> load_addr);
    printf("exec_add: 0x%x\n", head -> exec_add);
    printf("data_word_offset_img: 0x%x: 0x%x\n", \
            head-> data_word_offset_img, head-> data_word_offset_img *4);
    printf("attribute: 0x%x\n", head-> attribute);
    printf("section_count: 0x%x\n", head -> section_count);
    printf("sum: 0x%x\n", head -> sum);
    printf("image_word_offset: 0x%x\n", head-> image_word_offset);
    printf("auth_c_off: 0x%x\n", head-> auth_c_off);
    printf("head_sum: 0x%x\n", head-> head_sum);
}

int main(int argc, char * argv[])
{
    unsigned int vsion;
    char * filename = "BOOT.BIN";
    if(argc == 2)
    {
        filename =  argv[1];
    }
    printf("filename: %s\n", filename);
    int fd = open(filename, O_RDONLY);
    union BOOT_HEAD_U data;  
    read(fd, &data.buff, 0xa0);
    print_head(& data.data);

    lseek(fd, data.data.image_head_table, SEEK_SET);
    image_header_table image_table;
    read(fd, &image_table.buff, 0x40);
    print_image_header_tabel(&image_table.header_table);

    image_header image_head;
    for (int i = 0 ; i< image_table.header_table.count; i ++)
    {
        read(fd, &image_head.buff, 0x40);
        print_image_header(&image_head. header);
    }

    lseek(fd, data.data.partition_head_table, SEEK_SET);
    part_header part;
    for (int i = 0 ; i< image_table.header_table.count; i ++)
    {
        read(fd, &part.buff, 0x40);
        print_part_header(& part.part_header, i);
    }
    return 0;
}
